package cn.foolishbird.hamal.frame.generator;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;


/**
 * 生成器几大组件
 * 1. GlobalConfig     全局配置
 * 2. DataSourceConfig  数据源配置
 * 3. PackageInfo      包 名设置
 * 4. StrategyConfig   命名等生成策略
 * 5. TemplateConfig   模板配置
 * 6. InjectionConfig   注入配置,通过注入配置,实现自定效果
 *
 * @author Eric
 * @since 2019-5-6
 */
public class MyCodeGenerator {

    /**
     * 项目 相对操作系统的位置
     */
    private static final String OUTPUT_DIR = "E:\\public-project\\hamal";

    /**
     * 代码相对项目输出的位置
     */
    private static final String CODE_PATH = "\\src\\main\\java";
    /**
     * 作者
     */
    private static final String AUTHOR = "Eric";

    /**
     * 数据库相关配置信息
     */
    private static final String DRIVER_URL = "jdbc:mysql://212.64.43.223:13306/hamal?useUnicode=true&useSSL=false&characterEncoding=utf8";
    private static final String DRIVER = "com.mysql.jdbc.Driver";
    private static final String USERNAME = "lht";
    private static final String PASSWORD = "lht4815.";


    /**
     * 包名相关配置信息
     */
    private static final String BASE_PACKAGE_NAME = "cn.foolishbird.hamal.frame.sys";
    private static final String ENTITY_PACKAGE = "entity";
    private static final String MAPPER_PACKAGER = "mapper";
    private static final String MAPPER_XML_PACKAGER = "mapper.xml";
    private static final String SERVICE_PACKAGE = "service";
    private static final String SERVICE_IMPL_PACKAGE = "service.impl";
    private static final String CONTROLLER_PACKAGE = "controller";
    private static final String CUSTOM_XML_PACKAGE = "/src/main/resources/mapper/sys/";
    private static final String CUSTOM_XML_SUFFIX = "Mapper";
    private static final String CUSTOM_XML_TEMPLATE = "/templates/mapper.xml.ftl";


    /**
     * 生成策略相关
     */
    private static final String TABLE_PREFIX = "";
    private static final String[] SUPPER_ENTITY_FIELD =
            new String[]{"id", "create_time", "update_time", "priority", "del_flag"};
    private static final String SUPPER_ENTITY = "cn.foolishbird.hamal.frame.base.CustomBaseEntity";
    private static final String SUPPER_MAPPER = "cn.foolishbird.hamal.frame.base.CustomBaseMapper";
    private static final String SUPPER_ISERVICE = "cn.foolishbird.hamal.frame.base.CustomService";
    private static final String SUPPER_SERVICE_IMPL = "cn.foolishbird.hamal.frame.base.CustomBaseServiceImpl";
    private static final String SUPPER_CONTROLLER = "cn.foolishbird.hamal.frame.base.CustomBaseController";
    private static final String VERSION_FIELD = "version";
    private static final String DELETE_FLAG = "del_flag";

    /**
     * @param args
     * @return void
     * @throws
     * @author Eric
     * @date 2019/5/6
     **/
    public static void main(String[] args) {
        AutoGenerator generator = new AutoGenerator();
        generator.setGlobalConfig(getGlobConfig());
        generator.setDataSource(getDataSourceConfig());
        generator.setStrategy(getStrategyConfig("sys_user_token"));
        generator.setPackageInfo(getPackageConfig());
        generator.setTemplate(getTemplateConfig());
        generator.setCfg(getInjectionConfig());

        generator.setTemplateEngine(new FreemarkerTemplateEngine());
        generator.execute();
    }

    public static GlobalConfig getGlobConfig() {
        GlobalConfig config = new GlobalConfig();
        config.setOutputDir(OUTPUT_DIR + CODE_PATH);
        //是否覆盖已有文件, 默认是false
        config.setFileOverride(false);
        //是否在代码生成完成后，开发对应路径，默认是true
        config.setOpen(false);
        //是否在xml开启二级缓存，  默认是false
        config.setEnableCache(false);
        //作者名字
        config.setAuthor(AUTHOR);
        //是否开启 kotlinm模式，模式是false
        config.setKotlin(false);
        //是否开启swagger模式，默认是关闭，这里我开启
        config.setSwagger2(false);
        //是否开启activeRecord模式，默认关闭
        config.setActiveRecord(false);
        //是否开始baseResultMap ,默认关闭，这里开启后，xml 里面生成<resultMap>标签
        config.setBaseResultMap(false);
        //是否开启baseColumList 默认关闭，这里开启后 ，xml里面生成 <sql>标签，包含所有列，用于<include>引入
        config.setBaseColumnList(false);
        //时间类型对应策略，默认是TIME_PACK
        config.setDateType(DateType.TIME_PACK);
        //实例类名生成策略 %sDTO
        config.setEntityName(null);
        //Mapper 命名生成策略  %sMapper %sDao
        config.setMapperName(null);
        config.setXmlName(null);
        config.setServiceName(null);
        config.setServiceImplName(null);
        config.setControllerName(null);
        //id生成策略 模式是null   INPUT 应该是输入的意思
        config.setIdType(IdType.INPUT);

        return config;
    }

    public static DataSourceConfig getDataSourceConfig() {

        DataSourceConfig config = new DataSourceConfig();
//        config.setDbQuery()
//        config.setDbType()
//        config.setSchemaName() 数据库 schema name
//        config.setTypeConvert()
        config.setUrl(DRIVER_URL);
        config.setDriverName(DRIVER);
        config.setUsername(USERNAME);
        config.setPassword(PASSWORD);

        return config;

    }

    public static StrategyConfig getStrategyConfig(String include) {
        StrategyConfig config = new StrategyConfig();
        //是否开启首字母大学,测试了，好像没什么效果
        config.setCapitalMode(false);
        //跳过视图，感觉应该是oracle数据库类似，视图不生成，有机会测试下
        config.setSkipView(false);
        //下划线取消，变成驼峰
        config.setNaming(NamingStrategy.underline_to_camel);
        //下划线取消，编程驼峰
        config.setColumnNaming(NamingStrategy.underline_to_camel);
        //表前缀 不知道什么用,测试过了，添加，感觉没什么用啊，待以后更新
        config.setTablePrefix(TABLE_PREFIX);
//        config.setFieldPrefix();//字段前缀,同上
        //实例类父类     要写全限定名
        config.setSuperEntityClass(SUPPER_ENTITY);
        //父类字段，不会在 子类生成
        config.setSuperEntityColumns(SUPPER_ENTITY_FIELD);
        //同Entity
        config.setSuperMapperClass(SUPPER_MAPPER);
        //同Entity
        config.setSuperServiceClass(SUPPER_ISERVICE);
        //同Entity
        config.setSuperServiceImplClass(SUPPER_SERVICE_IMPL);
        //同Entity
        config.setSuperControllerClass(SUPPER_CONTROLLER);
        //包含表名,支持正则
        if (StringUtils.isNotBlank(include)) {
            config.setInclude(include);
        }
        //排除表名,支持正则  ,include exclude  同时只能存在一个
        config.setExclude(null);
        //是否生成实例常量,  这个不清楚干嘛,还需要测试
        config.setEntityColumnConstant(false);
        //是否开启lombok 建造者模式 .默认是false
        config.setEntityBuilderModel(true);
        //是否开启lombok 模式 ,默认是false
        config.setEntityLombokModel(true);
        //是否移除boolean 前 is
        config.setEntityBooleanColumnRemoveIsPrefix(false);
        //开启controller上面 @RestController注解
        config.setRestControllerStyle(true);
        // @RequestMapper 里面value    为true  通过-连接单词,  为false  驼峰命名
        config.setControllerMappingHyphenStyle(false);
        //是否生成字段注解 @TableField  注解
        config.setEntityTableFieldAnnotationEnable(true);
        //乐观锁版本号 字段名,和数据库进行匹配
        config.setVersionFieldName(VERSION_FIELD);
        //逻辑删除字段名
        config.setLogicDeleteFieldName(DELETE_FLAG);
        // 这里目前不知道干嘛的
        config.setTableFillList(null);
        return config;
    }

    public static PackageConfig getPackageConfig() {
        //路径生成策略
        //outputDir+父包名+父模块名+子包名
        PackageConfig config = new PackageConfig();
        config.setParent(BASE_PACKAGE_NAME);
        //模块名
        config.setModuleName(null);
        config.setEntity(ENTITY_PACKAGE);
        config.setMapper(MAPPER_PACKAGER);
        config.setXml(MAPPER_XML_PACKAGER);
        config.setService(SERVICE_PACKAGE);
        config.setServiceImpl(SERVICE_IMPL_PACKAGE);
        config.setController(CONTROLLER_PACKAGE);
        return config;
    }

    public static TemplateConfig getTemplateConfig() {
        TemplateConfig config = new TemplateConfig();
        config.setEntity("/templates/entity.java");
//        config.setEntityKt("/templates/entity.kt");
//        config.setMapper("/templates/mapper.java");
        config.setXml(null);
//        config.setService("/templates/service.java");
//        config.setServiceImpl("/templates/serviceImpl.java");
        config.setController(null);
        return config;
    }

    public static InjectionConfig getInjectionConfig() {
        InjectionConfig confg = new InjectionConfig() {
            @Override
            public void initMap() {
                System.out.println(this);
            }

//            @Override
//            public void initTableMap(TableInfo tableInfo) {
//
//            }
        };

        // 如果模板引擎是 freemarker
//        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";
        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(CUSTOM_XML_TEMPLATE) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
//                return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
//                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
                return OUTPUT_DIR + CUSTOM_XML_PACKAGE + tableInfo.getEntityName() + CUSTOM_XML_SUFFIX + StringPool.DOT_XML;
            }
        });

        focList.add(new FileOutConfig("/templates/MyController.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return OUTPUT_DIR + CODE_PATH + "/cn/foolishbird/hamal/frame/sys/" + CONTROLLER_PACKAGE + "/" + tableInfo.getEntityName() + "Controller" + StringPool.DOT_JAVA;
            }
        });

//        focList.add(new FileOutConfig("/templates/api.js.ftl") {
//            @Override
//            public String outputFile(TableInfo tableInfo) {
//                return "D:\\project\\me\\webpack\\chick-admin\\src\\api\\"+ Utils.firstAlphabetToUpper(tableInfo.getEntityName()) + ".js";
//            }
//        });
//        focList.add(new FileOutConfig("/templates/page.vue.ftl") {
//            @Override
//            public String outputFile(TableInfo tableInfo) {
//                return "D:\\project\\me\\webpack\\chick-admin\\src\\views\\permission\\"+ Utils.firstAlphabetToUpper(tableInfo.getEntityName()) + ".vue";
//            }
//        });

        confg.setFileOutConfigList(focList);

        return confg;
    }

}
